#!/bin/bash

os::homedir() {
  echo $HOME
}

os::username() {
  if [ "$USER" != "" ]; then
    echo $USER
    return
  fi

  local user=$(id -u -n)
  if [ "$user" != "" ]; then
    echo $user
    return
  fi

  log::error "Cannot get user by os::username"
  exit 1
}

os::shell() {
  echo $SHELL
}

os::bash_profile() {
  echo "$HOME/.bashrc"
}

os::zsh_profile() {
  echo "$HOME/.zshrc"
}

os::shell_profile() {
  if [ "$(os::is_zsh)" = "true" ]; then
    os::zsh_profile
  elif [ "$(os::is_bash)" = "true" ]; then
    os::bash_profile
  else
    echo "$HOME/.profile"
  fi
}

os::hostname() {
  echo $HOST
}

os::uptime() {
  echo $(uptime -p)
}

os::arch() {
  echo $(uname -m)
}

os::release() {
  local issue=""

  # Red Hat
  # cat /proc/version | grep "Red Hat" >> /dev/null 2&>1
  # if [ "$?" != "0" ]; then
  #   echo $(cat /proc/version | grep -o "Red Hat [^-]*")
  #   return
  # fi

  which lsb_release >>/dev/null 2>&1
  if [ "$?" = "0" ]; then
    issue=$(lsb_release -d)
  else
    issue=$(cat /etc/issue)
  fi

  local array=$issue
  local res=""

  for element in $array; do
    # echo "element: $element"
    if [ "$element" = "\n" ]; then
      continue
    fi

    if [ "$element" = "\l" ]; then
      continue
    fi

    if [ "$element" = "Description:" ]; then
      continue
    fi

    # core
    if [ "$res" = "" ]; then
      res=$element
    else
      res="$res $element"
    fi
  done

  echo $res
}

os::kernel() {
  echo $(uname -s)
}

os::pwd() {
  echo $PWD
}

os::tmp() {
  echo /tmp
}

#
os::is_bash() {
  echo $(os::shell) | grep -o bash >>/dev/null 2>&1
  if [ "$?" != "0" ]; then
    echo "false"
    return
  fi

  echo "true"
}

os::is_zsh() {
  echo $(os::shell) | grep -o zsh >>/dev/null 2>&1
  if [ "$?" != "0" ]; then
    echo "false"
    return
  fi

  echo "true"
}

os::is_macos() {
  local kernel=$(os::kernel)

  if [ "$kernel" = "Darwin" ]; then
    echo true
  else
    echo false
  fi
}

os::is_linux() {
  local kernel=$(os::kernel)

  if [ "$kernel" = "Linux" ]; then
    echo true
  else
    echo false
  fi
}

os::is_centos() {
  which yum >>/dev/null 2>&1
  if [ $? -eq 0 ]; then
    echo true
  else
    echo false
  fi
}

os::is_ubuntu() {
  which apt >>/dev/null 2>&1
  if [ $? -eq 0 ]; then
    echo true
  else
    echo false
  fi
}

os::is_alpine() {
  which apk >>/dev/null 2>&1
  if [ $? -eq 0 ]; then
    echo true
  else
    echo false
  fi
}

os::is_archlinux() {
  which pacman >>/dev/null 2>&1
  if [ $? -eq 0 ]; then
    echo true
  else
    echo false
  fi
}

os::is_federa() {
  which dnf >>/dev/null 2>&1
  if [ $? -eq 0 ]; then
    echo true
  else
    echo false
  fi
}

os::is_docker() {
  if [ -f "/.dockerenv" ]; then
    echo "true"
    return
  fi

  cat /proc/self/cgroup | grep docker >>/dev/null 2>&1
  if [ "$?" = "0" ]; then
    echo "true"
    return
  fi

  echo "false"
}

os::top() {
  htop -t
}

os::is_command_exist() {
  local command=$1
  command -v $command >>/dev/null 2>&1
  if [ "$?" = "0" ]; then
    echo "true"
  else
    echo "false"
  fi
}

os::is_support_color() {
  # if [ "$(echo $PS1)" != "" ]; then
  if [ "$TERM" = "xterm-256color" ]; then
    echo "true"
  else
    echo "false"
  fi
}

os::cpu_usage() {
  top -bn1 | grep Cpu | head -n 1 | awk '{printf "%.2f", $2}'
}

os::memory_usage() {
  # unit: MB
  # used total percent

  local type=$1
  local all=$(free -m | awk 'NR==2{printf "%s/%sMB (%.2f%%)", $3,$2,$3*100/$2 }')

  case $type in
  used)
    echo $all | awk -F '/' '{print $1}'
    ;;
  total)
    echo $all | awk -F '[/M]' '{print $2}'
    ;;
  percent)
    echo $all | awk -F '[(%]' '{print $2}'
    ;;
  *)
    echo $all
    ;;
  esac
}

os::disk_usage() {
  # unit: GB
  # used total percent

  local type=$1
  local all=$(df -h | awk '$NF=="/"{printf "%d/%dGB (%s)", $3,$2,$5}')

  case $type in
  used)
    echo $all | awk -F '/' '{print $1}'
    ;;
  total)
    echo $all | awk -F '[/G]' '{print $2}'
    ;;
  percent)
    echo $all | awk -F '[(%]' '{print $2}'
    ;;
  *)
    echo $all
    ;;
  esac
}

os::system_usage() {
  echo "cpu: $(os::cpu_usage)
memory: $(os::memory_usage)
disk: $(os::disk_usage)"
}

os::network_ip() {
  dig +short myip.opendns.com @resolver1.opendns.com
}

os::machine_id() {
  if [ "$(os::is_linux)" = "true" ]; then
    local machine_id0=/var/lib/dbus/machine-id
    local machine_id1=/etc/machine-id
    if [ -f $machine_id0 ]; then
      cat $machine_id0
    elif [ -f $machine_id1 ]; then
      cat $machine_id1
    else
      log::error "Cannot get machine id in linux"
      exit 1
    fi
  elif [ "$(os::is_macos)" = "true" ]; then
    echo $(ioreg -rd1 -c IOPlatformExpertDevice | grep "IOPlatformUUID" | awk -F '"' '{print $4}')
  else
    log::error "Cannot get machine id by unknown system"
    exit 1
  fi
}

os::rw_permission() {
  local path=$1
  # if [ -f $path ]; then
  #   if  [ ! -r $path ] || [ ! -w $path ]; then
  #     sudo chmod o+rw $path
  #   fi
  # fi

  # if [ -d $path ]; then
  #   if [ ! -w $path ]; then
  #     sudo chown -R $(os::username) $path
  #   fi
  # fi

  # path not exist
  if [ ! -e $path ]; then
    return
  fi

  if [ ! -r $path ] || [ ! -w $path ]; then
    sudo chmod a+rw $path

    log::debug "add rw permission: $path"
  fi
}

os::ensure_permission() {
  os::rw_permission $@
}

# @TODO
os::ensure_logs_permission() {
  os::ensure_permission $ZMICRO_LOG_PATH

  os::ensure_permission $ZMICRO_LOG_COMMON_PATH
  os::ensure_permission $ZMICRO_LOG_DEBUG_PATH
  os::ensure_permission $ZMICRO_LOG_ERROR_PATH
  os::ensure_permission $ZMICRO_LOG_UPDATE_PATH
  os::ensure_permission $ZMICRO_LOG_VERSION_PATH
  os::ensure_permission $ZMICRO_LOG_NOTIFY_PATH
}

os::is_pid_valid() {
  local pid=$1
  local pid_file=/proc/$pid/status
  if [ -f $pid_file ]; then
    echo "true"
  else
    echo "false"
  fi
}

os::get_pid_memory() {
  local pid=$1
  local pid_file=/proc/$pid/status
  if [ ! -f $pid_file ]; then
    echo "0"
    return
  fi

  local memory=$(cat $pid_file | grep VmRSS | awk '{print $2}')
  if [ -z "$memory" ]; then
    echo "0"
    return
  fi

  echo $memory
}

os::kill_pid() {
  local pid=$1
  if [ "$(os::is_pid_valid $pid)" = "true" ]; then
    # log "kill pid: $pid"
    kill -9 $pid
  fi
}

export -f os::homedir
export -f os::username
export -f os::shell
export -f os::shell_profile
export -f os::hostname
export -f os::uptime
export -f os::kernel

export -f os::pwd
export -f os::tmp

export -f os::is_bash
export -f os::is_zsh
export -f os::is_linux
export -f os::is_macos

export -f os::is_centos
export -f os::is_ubuntu
export -f os::is_alpine
export -f os::is_archlinux
export -f os::is_federa

export -f os::is_docker

export -f os::top
export -f os::is_command_exist
export -f os::is_support_color

export -f os::cpu_usage
export -f os::memory_usage
export -f os::disk_usage
export -f os::system_usage

export -f os::network_ip

export -f os::machine_id

export -f os::rw_permission
export -f os::ensure_permission
export -f os::ensure_logs_permission

export -f os::is_pid_valid
export -f os::get_pid_memory
export -f os::kill_pid
